4118b6a418gnL6AZsTdglC92YGqYTg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/highmem.h
42539fb5A9hsS3NFQ-2VY4y1TONZZQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/hypercall.h
40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/io.h
-42778a69MXZVxch4pQqYsMPS0WnNSg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/io_apic.h
40f5623aKXkBBxgpLx2NcvkncQ1Yyw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
40f5623aDMCsWOFO0jktZ4e8sjwvEg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h
40f5623arsFXkGdPvIqvFi3yFXGR0Q linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_pre.h
41aaf567a36esU-rUK7twPiv-yTFyw xen/arch/x86/mtrr/mtrr.h
41aaf567DcTL6pqVtLZJI5cSryyA1A xen/arch/x86/mtrr/state.c
3f12cff65EV3qOG2j37Qm0ShgvXGRw xen/arch/x86/nmi.c
+4051bcecFeq4DE70p4zGO5setf47CA xen/arch/x86/physdev.c
3ddb79bc7KxGCEJsgBnkDX7XjD_ZEQ xen/arch/x86/rwlock.c
3ddb79bcrD6Z_rUvSDgrvjyb4846Eg xen/arch/x86/setup.c
405b8599xI_PoEr3zZoJ2on-jdn7iw xen/arch/x86/shadow.c
41a61536SZbR6cj1ukWTb0DYU-vz9w xen/common/multicall.c
3ddb79bdD4SLmmdMD7yLW5HcUWucXw xen/common/page_alloc.c
3e54c38dkHAev597bPr71-hGzTdocg xen/common/perfc.c
-4051bcecFeq4DE70p4zGO5setf47CA xen/common/physdev.c
3ddb79bdHqdQpATqC0rmUZNbsb6L6A xen/common/resource.c
40589968dD2D1aejwSOvrROg7fOvGQ xen/common/sched_bvt.c
3e397e6619PgAfBbw2XFbXkewvUWgw xen/common/schedule.c
41a61536MFhNalgbVmYGXAhQsPTZNw xen/include/asm-x86/multicall.h
3ddb79c3xjYnrv5t3VqYlR4tNEOl4Q xen/include/asm-x86/page.h
3ddb79c3ysKUbxZuwKBRK3WXU2TlEg xen/include/asm-x86/pci.h
+42422fb0FVX-TJkSvAXnbfwMf19XFA xen/include/asm-x86/physdev.h
3ddb79c2QF5-pZGzuX4QukPCDAl59A xen/include/asm-x86/processor.h
40cf1596bim9F9DNdV75klgRSZ6Y2A xen/include/asm-x86/regs.h
3ddb79c2plf7ciNgoNjU-RsbUzawsw xen/include/asm-x86/rwlock.h
3ddb79c0MOVXq8qZDQRGb6z64_xAwg xen/include/xen/pci_ids.h
3e54c38dlSCVdyVM4PKcrSfzLLxWUQ xen/include/xen/perfc.h
3e54c38de9SUSYSAwxDf_DwkpAnQFA xen/include/xen/perfc_defn.h
-42422fb0FVX-TJkSvAXnbfwMf19XFA xen/include/xen/physdev.h
3ddb79c04nQVR3EYM5L4zxDV_MCo1g xen/include/xen/prefetch.h
3e4540ccU1sgCx8seIMGlahmMfv7yQ xen/include/xen/reboot.h
40589969nPq3DMzv24RDb5LXE9brHw xen/include/xen/sched-if.h
#include <linux/config.h>
#include <linux/init.h>
-#include <asm/apic.h>
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/mc146818rtc.h>
+#include <linux/kernel_stat.h>
+#include <linux/sysdev.h>
+
+#include <asm/atomic.h>
+#include <asm/smp.h>
+#include <asm/mtrr.h>
+#include <asm/mpspec.h>
+#include <asm/desc.h>
+#include <asm/arch_hooks.h>
+#include <asm/hpet.h>
+
+#include <mach_apic.h>
+
+#include "io_ports.h"
+
+/*
+ * Debug level
+ */
int apic_verbosity;
int get_physical_broadcast(void)
*/
int __init APIC_init_uniprocessor (void)
{
+#ifdef CONFIG_X86_IO_APIC
+ if (smp_found_config)
+ if (!skip_ioapic_setup && nr_ioapics)
+ setup_IO_APIC();
+#endif
+
return 0;
}
#include <asm/smp.h>
#include <asm/desc.h>
#include <asm/timer.h>
-#include <asm/io_apic.h>
-#include <asm/apic.h>
#include <mach_apic.h>
#include "io_ports.h"
-int (*ioapic_renumber_irq)(int ioapic, int irq);
-atomic_t irq_mis_count;
+#ifdef CONFIG_XEN
+
+#include <asm-xen/xen-public/xen.h>
+#include <asm-xen/xen-public/physdev.h>
+
+/* Fake i8259 */
+#define make_8259A_irq(_irq) (io_apic_irqs &= ~(1UL<<(_irq)))
+#define disable_8259A_irq(_irq) ((void)0)
+#define i8259A_irq_pending(_irq) (0)
unsigned long io_apic_irqs;
+static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg)
+{
+ physdev_op_t op;
+ int ret;
+
+ op.cmd = PHYSDEVOP_APIC_READ;
+ op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
+ op.u.apic_op.offset = reg;
+ ret = HYPERVISOR_physdev_op(&op);
+ if (ret)
+ return ret;
+ return op.u.apic_op.value;
+}
+
+static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+{
+ physdev_op_t op;
+
+ op.cmd = PHYSDEVOP_APIC_WRITE;
+ op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
+ op.u.apic_op.offset = reg;
+ op.u.apic_op.value = value;
+ HYPERVISOR_physdev_op(&op);
+}
+
+#define io_apic_read(a,r) xen_io_apic_read(a,r)
+#define io_apic_write(a,r,v) xen_io_apic_write(a,r,v)
+
+#endif /* CONFIG_XEN */
+
+int (*ioapic_renumber_irq)(int ioapic, int irq);
+atomic_t irq_mis_count;
+
static DEFINE_SPINLOCK(ioapic_lock);
/*
entry->pin = pin;
}
+#ifndef CONFIG_XEN
/*
* Reroute an IRQ to a different pin.
*/
}
spin_unlock_irqrestore(&ioapic_lock, flags);
}
+#else
+#define clear_IO_APIC() ((void)0)
+#endif
#if defined(CONFIG_IRQBALANCE)
# include <asm/processor.h> /* kernel_thread() */
#ifndef CONFIG_SMP
void fastcall send_IPI_self(int vector)
{
-#if 1
- return;
-#else
+#ifndef CONFIG_XEN
unsigned int cfg;
/*
}
#endif /* !CONFIG_SMP */
-
/*
* support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
* specific CPU-side IRQs.
return -1;
}
+#ifndef CONFIG_XEN
/*
* Find the pin to which IRQ[irq] (ISA) is connected
*/
}
return -1;
}
+#endif
/*
* Find a specific PCI IRQ entry.
return best_guess;
}
+#ifndef CONFIG_XEN
/*
* This function currently is only a helper for the i386 smp boot process where
* we need to reprogram the ioredtbls to cater for the cpus which have come online
}
}
+#endif /* !CONFIG_XEN */
/*
* EISA Edge/Level control register, ELCR
}
/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
+u8 irq_vector[NR_IRQ_VECTORS]; /* = { FIRST_DEVICE_VECTOR , 0 }; */
int assign_irq_vector(int irq)
{
return current_vector;
}
+#ifndef CONFIG_XEN
static struct hw_interrupt_type ioapic_level_type;
static struct hw_interrupt_type ioapic_edge_type;
irq_desc[vector].handler = &ioapic_level_type;
else
irq_desc[vector].handler = &ioapic_edge_type;
-#if 0
set_intr_gate(vector, interrupt[vector]);
-#endif
} else {
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
trigger == IOAPIC_LEVEL)
irq_desc[irq].handler = &ioapic_level_type;
else
irq_desc[irq].handler = &ioapic_edge_type;
-#if 0
set_intr_gate(vector, interrupt[irq]);
-#endif
}
}
+#else
+#define ioapic_register_intr(_irq,_vector,_trigger) ((void)0)
+#endif
void __init setup_IO_APIC_irqs(void)
{
else
add_pin_to_irq(irq, apic, pin);
- if (!apic && !IO_APIC_IRQ(irq))
+ if (/*!apic &&*/ !IO_APIC_IRQ(irq))
continue;
if (IO_APIC_IRQ(irq)) {
entry.vector = vector;
ioapic_register_intr(irq, vector, IOAPIC_AUTO);
-#if 0
if (!apic && (irq < 16))
disable_8259A_irq(irq);
-#endif
}
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
/*
* Set up the 8259A-master output pin:
*/
+#ifndef CONFIG_XEN
void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
{
struct IO_APIC_route_entry entry;
memset(&entry,0,sizeof(entry));
-#if 0
disable_8259A_irq(0);
-#endif
/* mask LVT0 */
apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
spin_unlock_irqrestore(&ioapic_lock, flags);
-#if 0
enable_8259A_irq(0);
-#endif
}
static inline void UNEXPECTED_IO_APIC(void)
void /*__init*/ print_local_APIC(void * dummy)
{
-#if 0
unsigned int v, ver, maxlvt;
if (apic_verbosity == APIC_QUIET)
v = apic_read(APIC_TDCR);
printk(KERN_DEBUG "... APIC TDCR: %08x\n", v);
printk("\n");
-#endif
}
void print_all_local_APICs (void)
v = inb(0x4d1) << 8 | inb(0x4d0);
printk(KERN_DEBUG "... PIC ELCR: %04x\n", v);
}
+#else
+void __init print_IO_APIC(void) { }
+#endif /* !CONFIG_XEN */
static void __init enable_IO_APIC(void)
{
*/
clear_IO_APIC();
-#if 0
+#ifndef CONFIG_XEN
disconnect_bsp_APIC();
#endif
}
* by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999
*/
-#ifndef CONFIG_X86_NUMAQ
+#if !defined(CONFIG_XEN) && !defined(CONFIG_X86_NUMAQ)
static void __init setup_ioapic_ids_from_mpc(void)
{
union IO_APIC_reg_00 reg_00;
static void __init setup_ioapic_ids_from_mpc(void) { }
#endif
+#ifndef CONFIG_XEN
/*
* There is a nasty bug in some older SMP boards, their mptable lies
* about the timer IRQ. We do the following to work around the situation:
unsigned long flags;
spin_lock_irqsave(&ioapic_lock, flags);
-#if 0
if (irq < 16) {
disable_8259A_irq(irq);
if (i8259A_irq_pending(irq))
was_pending = 1;
}
-#endif
__unmask_IO_APIC_irq(irq);
spin_unlock_irqrestore(&ioapic_lock, flags);
.end = end_level_ioapic,
.set_affinity = set_ioapic_affinity,
};
+#endif /* !CONFIG_XEN */
static inline void init_IO_APIC_traps(void)
{
* so default to an old-fashioned 8259
* interrupt if we can..
*/
-#if 0
if (irq < 16)
make_8259A_irq(irq);
+#ifndef CONFIG_XEN
else
-#endif
/* Strange. Oh, well.. */
irq_desc[irq].handler = &no_irq_type;
+#endif
}
}
}
+#ifndef CONFIG_XEN
static void enable_lapic_irq (unsigned int irq)
{
unsigned long v;
*/
apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
-#if 0
on_each_cpu(enable_NMI_through_LVT0, NULL, 1, 1);
-#endif
apic_printk(APIC_VERBOSE, " done.\n");
}
*/
static inline void check_timer(void)
{
-#if 0
int pin1, pin2;
int vector;
printk(" failed :(.\n");
panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a "
"report. Then try booting with the 'noapic' option");
-#endif
}
+#else
+#define check_timer() ((void)0)
+#endif
/*
*
*/
if (!acpi_ioapic)
setup_ioapic_ids_from_mpc();
-#if 0
+#ifndef CONFIG_XEN
sync_Arb_IDs();
#endif
setup_IO_APIC_irqs();
int __init io_apic_get_unique_id (int ioapic, int apic_id)
{
+#ifndef CONFIG_XEN
union IO_APIC_reg_00 reg_00;
static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
physid_mask_t tmp;
apic_id = reg_00.bits.ID;
}
-#if 0
/*
* Every APIC in a system must have a unique ID or we get lots of nice
* 'stuck on smp_invalidate_needed IPI wait' messages.
if (reg_00.bits.ID != apic_id)
panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
}
-#endif
apic_printk(APIC_VERBOSE, KERN_INFO
"IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
+#endif /* !CONFIG_XEN */
return apic_id;
}
mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq,
edge_level, active_high_low);
-#ifndef CONFIG_XEN
ioapic_register_intr(irq, entry.vector, edge_level);
if (!ioapic && (irq < 16))
disable_8259A_irq(irq);
-#endif
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
+++ /dev/null
-#ifndef __ASM_IO_APIC_H
-#define __ASM_IO_APIC_H
-
-#include <linux/config.h>
-#include <asm/types.h>
-#include <asm/mpspec.h>
-
-#include <asm-xen/xen-public/xen.h>
-#include <asm-xen/xen-public/physdev.h>
-
-/*
- * Intel IO-APIC support for SMP and UP systems.
- *
- * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar
- */
-
-#ifdef CONFIG_X86_IO_APIC
-
-#ifdef CONFIG_PCI_MSI
-static inline int use_pci_vector(void) {return 1;}
-static inline void disable_edge_ioapic_vector(unsigned int vector) { }
-static inline void mask_and_ack_level_ioapic_vector(unsigned int vector) { }
-static inline void end_edge_ioapic_vector (unsigned int vector) { }
-#define startup_level_ioapic startup_level_ioapic_vector
-#define shutdown_level_ioapic mask_IO_APIC_vector
-#define enable_level_ioapic unmask_IO_APIC_vector
-#define disable_level_ioapic mask_IO_APIC_vector
-#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_vector
-#define end_level_ioapic end_level_ioapic_vector
-#define set_ioapic_affinity set_ioapic_affinity_vector
-
-#define startup_edge_ioapic startup_edge_ioapic_vector
-#define shutdown_edge_ioapic disable_edge_ioapic_vector
-#define enable_edge_ioapic unmask_IO_APIC_vector
-#define disable_edge_ioapic disable_edge_ioapic_vector
-#define ack_edge_ioapic ack_edge_ioapic_vector
-#define end_edge_ioapic end_edge_ioapic_vector
-#else
-static inline int use_pci_vector(void) {return 0;}
-static inline void disable_edge_ioapic_irq(unsigned int irq) { }
-static inline void mask_and_ack_level_ioapic_irq(unsigned int irq) { }
-static inline void end_edge_ioapic_irq (unsigned int irq) { }
-#define startup_level_ioapic startup_level_ioapic_irq
-#define shutdown_level_ioapic mask_IO_APIC_irq
-#define enable_level_ioapic unmask_IO_APIC_irq
-#define disable_level_ioapic mask_IO_APIC_irq
-#define mask_and_ack_level_ioapic mask_and_ack_level_ioapic_irq
-#define end_level_ioapic end_level_ioapic_irq
-#define set_ioapic_affinity set_ioapic_affinity_irq
-
-#define startup_edge_ioapic startup_edge_ioapic_irq
-#define shutdown_edge_ioapic disable_edge_ioapic_irq
-#define enable_edge_ioapic unmask_IO_APIC_irq
-#define disable_edge_ioapic disable_edge_ioapic_irq
-#define ack_edge_ioapic ack_edge_ioapic_irq
-#define end_edge_ioapic end_edge_ioapic_irq
-#endif
-
-#define IO_APIC_BASE(idx) \
- ((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \
- + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK)))
-
-/*
- * The structure of the IO-APIC:
- */
-union IO_APIC_reg_00 {
- u32 raw;
- struct {
- u32 __reserved_2 : 14,
- LTS : 1,
- delivery_type : 1,
- __reserved_1 : 8,
- ID : 8;
- } __attribute__ ((packed)) bits;
-};
-
-union IO_APIC_reg_01 {
- u32 raw;
- struct {
- u32 version : 8,
- __reserved_2 : 7,
- PRQ : 1,
- entries : 8,
- __reserved_1 : 8;
- } __attribute__ ((packed)) bits;
-};
-
-union IO_APIC_reg_02 {
- u32 raw;
- struct {
- u32 __reserved_2 : 24,
- arbitration : 4,
- __reserved_1 : 4;
- } __attribute__ ((packed)) bits;
-};
-
-union IO_APIC_reg_03 {
- u32 raw;
- struct {
- u32 boot_DT : 1,
- __reserved_1 : 31;
- } __attribute__ ((packed)) bits;
-};
-
-/*
- * # of IO-APICs and # of IRQ routing registers
- */
-extern int nr_ioapics;
-extern int nr_ioapic_registers[MAX_IO_APICS];
-
-enum ioapic_irq_destination_types {
- dest_Fixed = 0,
- dest_LowestPrio = 1,
- dest_SMI = 2,
- dest__reserved_1 = 3,
- dest_NMI = 4,
- dest_INIT = 5,
- dest__reserved_2 = 6,
- dest_ExtINT = 7
-};
-
-struct IO_APIC_route_entry {
- __u32 vector : 8,
- delivery_mode : 3, /* 000: FIXED
- * 001: lowest prio
- * 111: ExtINT
- */
- dest_mode : 1, /* 0: physical, 1: logical */
- delivery_status : 1,
- polarity : 1,
- irr : 1,
- trigger : 1, /* 0: edge, 1: level */
- mask : 1, /* 0: enabled, 1: disabled */
- __reserved_2 : 15;
-
- union { struct { __u32
- __reserved_1 : 24,
- physical_dest : 4,
- __reserved_2 : 4;
- } physical;
-
- struct { __u32
- __reserved_1 : 24,
- logical_dest : 8;
- } logical;
- } dest;
-
-} __attribute__ ((packed));
-
-/*
- * MP-BIOS irq configuration table structures:
- */
-
-/* I/O APIC entries */
-extern struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
-
-/* # of MP IRQ source entries */
-extern int mp_irq_entries;
-
-/* MP IRQ source entries */
-extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
-
-/* non-0 if default (table-less) MP configuration */
-extern int mpc_default_type;
-
-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
-{
- physdev_op_t op;
- int ret;
-
- op.cmd = PHYSDEVOP_APIC_READ;
- op.u.apic_op.apic = apic;
- op.u.apic_op.offset = reg;
- ret = HYPERVISOR_physdev_op(&op);
- if (ret)
- return ret;
- return op.u.apic_op.value;
-}
-
-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
-{
- physdev_op_t op;
-
- op.cmd = PHYSDEVOP_APIC_WRITE;
- op.u.apic_op.apic = apic;
- op.u.apic_op.offset = reg;
- op.u.apic_op.value = value;
- HYPERVISOR_physdev_op(&op);
-}
-
-/*
- * Re-write a value: to be used for read-modify-write
- * cycles where the read already set up the index register.
- *
- * Older SiS APIC requires we rewrite the index regiser
- */
-extern int sis_apic_bug;
-static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
-{
- if (sis_apic_bug)
- *IO_APIC_BASE(apic) = reg;
- *(IO_APIC_BASE(apic)+4) = value;
-}
-
-/* 1 if "noapic" boot option passed */
-extern int skip_ioapic_setup;
-
-/*
- * If we use the IO-APIC for IRQ routing, disable automatic
- * assignment of PCI IRQ's.
- */
-#define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
-
-#ifdef CONFIG_ACPI_BOOT
-extern int io_apic_get_unique_id (int ioapic, int apic_id);
-extern int io_apic_get_version (int ioapic);
-extern int io_apic_get_redir_entries (int ioapic);
-extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low);
-#endif /*CONFIG_ACPI_BOOT*/
-
-extern int (*ioapic_renumber_irq)(int ioapic, int irq);
-
-#else /* !CONFIG_X86_IO_APIC */
-#define io_apic_assign_pci_irqs 0
-#endif
-
-extern int assign_irq_vector(int irq);
-
-#endif
int func,
int enable)
{
- dom0_op_t op;
-
- op.cmd = DOM0_PCIDEV_ACCESS;
- op.u.pcidev_access.domain = (domid_t)domid;
- op.u.pcidev_access.bus = bus;
- op.u.pcidev_access.dev = dev;
- op.u.pcidev_access.func = func;
- op.u.pcidev_access.enable = enable;
-
- return do_dom0_op(xc_handle, &op);
+ errno = ENOSYS;
+ return -1;
}
unsigned long pkern_entry;
unsigned long pkern_end;
- extern void physdev_init_dom0(struct domain *);
-
//printf("construct_dom0: starting\n");
/* Sanity! */
#ifndef CLONE_DOMAIN0
#endif
console_endboot(strstr(cmdline, "tty0") != NULL);
- /* DOM0 gets access to everything. */
-#ifdef CLONE_DOMAIN0
-if (d == dom0)
-#endif
- physdev_init_dom0(d);
-
set_bit(DF_CONSTRUCTED, &d->d_flags);
new_thread(ed, pkern_entry, 0, 0);
printk("dump_pageframe_info not implemented\n");
}
-///////////////////////////////
-// from common/physdev.c
-///////////////////////////////
-void
-physdev_init_dom0(struct domain *d)
-{
-}
-
-int
-physdev_pci_access_modify(domid_t id, int bus, int dev, int func, int enable)
-{
- return -EINVAL;
-}
-
-void physdev_modify_ioport_access_range(struct domain *d, int enable,
- int port, int num)
-{
- printk("physdev_modify_ioport_access_range not implemented\n");
- dummy();
-}
-
-void physdev_destroy_state(struct domain *d)
-{
- printk("physdev_destroy_state not implemented\n");
- dummy();
-}
-
///////////////////////////////
// called from arch/ia64/head.S
///////////////////////////////
unsigned int opt_tbuf_size = 10;
/* opt_sched: scheduler - default to Borrowed Virtual Time */
char opt_sched[10] = "bvt";
-/* opt_physdev_dom0_hide: list of PCI slots to hide from domain 0. */
-/* Format is '(%02x:%02x.%1x)(%02x:%02x.%1x)' and so on. */
-char opt_physdev_dom0_hide[200] = "";
/* opt_leveltrigger, opt_edgetrigger: Force an IO-APIC-routed IRQ to be */
/* level- or edge-triggered. */
/* Example: 'leveltrigger=4,5,6,20 edgetrigger=21'. */
#include <asm/vmx.h>
#include <asm/vmx_vmcs.h>
#include <asm/msr.h>
+#include <asm/physdev.h>
#include <xen/kernel.h>
#include <public/io/ioreq.h>
#include <xen/multicall.h>
BUG_ON(d->cpuset != 0);
+ physdev_destroy_state(d);
+
ptwr_destroy(d);
/* Release device mappings of other domains */
int irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 };
-#ifdef CONFIG_VMX
int vector_irq[256];
-#endif
int assign_irq_vector(int irq)
{
panic("ran out of interrupt sources!");
IO_APIC_VECTOR(irq) = current_vector;
-#ifdef CONFIG_VMX
+
vector_irq[current_vector] = irq;
- printk("vector_irq[%x] = %d\n", current_vector, irq);
-#endif
+ DPRINTK("vector_irq[%x] = %d\n", current_vector, irq);
+
return current_vector;
}
panic("IO-APIC + timer doesn't work! pester mingo@redhat.com");
}
+#define NR_IOAPIC_BIOSIDS 256
+static u8 ioapic_biosid_to_apic_enum[NR_IOAPIC_BIOSIDS];
+static void store_ioapic_biosid_mapping(void)
+{
+ u8 apic;
+ memset(ioapic_biosid_to_apic_enum, ~0, NR_IOAPIC_BIOSIDS);
+ for ( apic = 0; apic < nr_ioapics; apic++ )
+ ioapic_biosid_to_apic_enum[mp_ioapics[apic].mpc_apicid] = apic;
+}
+
/*
*
* IRQ's that are handled by the old PIC in all cases:
void __init setup_IO_APIC(void)
{
+ store_ioapic_biosid_mapping();
+
enable_IO_APIC();
io_apic_irqs = ~PIC_IRQS;
}
__initcall(ioapic_trigger_setup);
+
+int ioapic_guest_read(int apicid, int address, u32 *pval)
+{
+ u32 val;
+ int apicenum;
+ struct IO_APIC_reg_00 reg_00;
+ unsigned long flags;
+
+ if ( (apicid >= NR_IOAPIC_BIOSIDS) ||
+ ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) )
+ return -EINVAL;
+
+ spin_lock_irqsave(&ioapic_lock, flags);
+ val = io_apic_read(apicenum, address);
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+
+ /* Rewrite APIC ID to what the BIOS originally specified. */
+ if ( address == 0 )
+ {
+ *(int *)®_00 = val;
+ reg_00.ID = apicid;
+ val = *(u32 *)®_00;
+ }
+
+ *pval = val;
+ return 0;
+}
+
+int ioapic_guest_write(int apicid, int address, u32 val)
+{
+ int apicenum, pin, irq;
+ struct IO_APIC_route_entry rte = { 0 };
+ unsigned long flags;
+
+ if ( (apicid >= NR_IOAPIC_BIOSIDS) ||
+ ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) )
+ return -EINVAL;
+
+ /* Only write to the first half of a route entry. */
+ if ( (address < 0x10) || (address & 1) )
+ return 0;
+
+ pin = (address - 0x10) >> 1;
+
+ rte.dest.logical.logical_dest = target_cpus();
+ *(int *)&rte = val;
+
+ /* Make sure we handle edge/level triggering correctly. */
+ if ( !rte.mask )
+ {
+ irq = vector_irq[rte.vector];
+ if ( !IO_APIC_IRQ(irq) )
+ return 0;
+ irq_desc[irq].handler = rte.trigger ?
+ &ioapic_level_irq_type: &ioapic_edge_irq_type;
+ }
+
+ spin_lock_irqsave(&ioapic_lock, flags);
+ io_apic_write(apicenum, 0x10 + 2 * pin, *(((int *)&rte) + 0));
+ io_apic_write(apicenum, 0x11 + 2 * pin, *(((int *)&rte) + 1));
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+
+ return 0;
+}
--- /dev/null
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/types.h>
+#include <xen/sched.h>
+#include <xen/irq.h>
+#include <xen/event.h>
+#include <asm/smpboot.h>
+#include <public/xen.h>
+#include <public/physdev.h>
+
+extern void (*interrupt[])(void);
+
+extern int ioapic_guest_read(int apicid, int address, u32 *pval);
+extern int ioapic_guest_write(int apicid, int address, u32 pval);
+
+void physdev_modify_ioport_access_range(
+ struct domain *d, int enable, int port, int num)
+{
+ int i;
+ for ( i = port; i < (port + num); i++ )
+ (enable ? clear_bit : set_bit)(i, d->arch.iobmp_mask);
+}
+
+void physdev_destroy_state(struct domain *d)
+{
+ xfree(d->arch.iobmp_mask);
+ d->arch.iobmp_mask = NULL;
+}
+
+/* Check if a domain controls a device with IO memory within frame @pfn.
+ * Returns: 1 if the domain should be allowed to map @pfn, 0 otherwise. */
+int domain_iomem_in_pfn(struct domain *p, unsigned long pfn)
+{
+ return 0;
+}
+
+/*
+ * Demuxing hypercall.
+ */
+long do_physdev_op(physdev_op_t *uop)
+{
+ physdev_op_t op;
+ long ret;
+ int irq;
+
+ if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
+ return -EFAULT;
+
+ switch ( op.cmd )
+ {
+ case PHYSDEVOP_IRQ_UNMASK_NOTIFY:
+ ret = pirq_guest_unmask(current->domain);
+ break;
+
+ case PHYSDEVOP_IRQ_STATUS_QUERY:
+ irq = op.u.irq_status_query.irq;
+ ret = -EINVAL;
+ if ( (irq < 0) || (irq >= NR_IRQS) )
+ break;
+ op.u.irq_status_query.flags = 0;
+ /* Edge-triggered interrupts don't need an explicit unmask downcall. */
+ if ( strstr(irq_desc[irq].handler->typename, "edge") == NULL )
+ op.u.irq_status_query.flags |= PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY;
+ ret = 0;
+ break;
+
+ case PHYSDEVOP_APIC_READ:
+ ret = -EPERM;
+ if ( !IS_PRIV(current->domain) )
+ break;
+ ret = ioapic_guest_read(
+ op.u.apic_op.apic, op.u.apic_op.offset, &op.u.apic_op.value);
+ break;
+
+ case PHYSDEVOP_APIC_WRITE:
+ ret = -EPERM;
+ if ( !IS_PRIV(current->domain) )
+ break;
+ ret = ioapic_guest_write(
+ op.u.apic_op.apic, op.u.apic_op.offset, op.u.apic_op.value);
+ break;
+
+ case PHYSDEVOP_ASSIGN_VECTOR:
+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
+ if ( (irq = op.u.irq_op.irq) >= NR_IRQS )
+ return -EINVAL;
+
+ op.u.irq_op.vector = assign_irq_vector(irq);
+ set_intr_gate(op.u.irq_op.vector, interrupt[irq]);
+ ret = 0;
+ break;
+
+ case PHYSDEVOP_SET_IOPL:
+ ret = -EINVAL;
+ if ( op.u.set_iopl.iopl > 3 )
+ break;
+ ret = 0;
+ current->arch.iopl = op.u.set_iopl.iopl;
+ break;
+
+ case PHYSDEVOP_SET_IOBITMAP:
+ ret = -EINVAL;
+ if ( !access_ok(op.u.set_iobitmap.bitmap, IOBMP_BYTES) ||
+ (op.u.set_iobitmap.nr_ports > 65536) )
+ break;
+ ret = 0;
+ current->arch.iobmp = (u8 *)op.u.set_iobitmap.bitmap;
+ current->arch.iobmp_limit = op.u.set_iobitmap.nr_ports;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if ( copy_to_user(uop, &op, sizeof(op)) )
+ ret = -EFAULT;
+
+ return ret;
+}
+
+/* Domain 0 has read access to all devices. */
+void physdev_init_dom0(struct domain *d)
+{
+ /* Access to all I/O ports. */
+ d->arch.iobmp_mask = xmalloc_array(u8, IOBMP_BYTES);
+ BUG_ON(d->arch.iobmp_mask == NULL);
+ memset(d->arch.iobmp_mask, 0, IOBMP_BYTES);
+
+ set_bit(DF_PHYSDEV, &d->d_flags);
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
ifeq ($(TARGET_ARCH),ia64)
OBJS := $(subst dom_mem_ops.o,,$(OBJS))
OBJS := $(subst grant_table.o,,$(OBJS))
-OBJS := $(subst physdev.o,,$(OBJS))
endif
ifneq ($(perfc),y)
#include <asm/domain_page.h>
#include <xen/trace.h>
#include <xen/console.h>
-#include <xen/physdev.h>
#include <public/sched_ctl.h>
extern long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op);
}
break;
- case DOM0_PCIDEV_ACCESS:
- {
- ret = physdev_pci_access_modify(op->u.pcidev_access.domain,
- op->u.pcidev_access.bus,
- op->u.pcidev_access.dev,
- op->u.pcidev_access.func,
- op->u.pcidev_access.enable);
- }
- break;
-
case DOM0_SCHED_ID:
{
op->u.sched_id.sched_id = sched_id();
INIT_LIST_HEAD(&d->page_list);
INIT_LIST_HEAD(&d->xenpage_list);
- /* Per-domain PCI-device list. */
- spin_lock_init(&d->pcidev_lock);
- INIT_LIST_HEAD(&d->pcidev_list);
-
if ( (d->id != IDLE_DOMAIN_ID) &&
((init_event_channels(d) != 0) || (grant_table_create(d) != 0)) )
{
}
-#ifndef CONFIG_IA64
-extern void physdev_destroy_state(struct domain *d);
-#else
-#define physdev_destroy_state(_d) ((void)0)
-#endif
-
void domain_kill(struct domain *d)
{
struct exec_domain *ed;
for_each_exec_domain(d, ed)
sched_rem_domain(ed);
domain_relinquish_resources(d);
- physdev_destroy_state(d);
put_domain(d);
}
}
+++ /dev/null
-/****************************************************************************
- * (c) 2004 - Rolf Neugebauer - Intel Research Cambridge
- * (c) 2004 - Keir Fraser - University of Cambridge
- ****************************************************************************
- *
- * Description: allows a domain to access devices on the PCI bus
- *
- * A guest OS may be given access to particular devices on the PCI bus.
- * For each domain a list of PCI devices is maintained, describing the
- * access mode for the domain.
- *
- * Guests can figure out the virtualised PCI space through normal PCI config
- * register access. Some of the accesses, in particular write accesses, are
- * faked. For example the sequence for detecting the IO regions, which requires
- * writes to determine the size of the region, is faked out by a very simple
- * state machine, preventing direct writes to the PCI config registers by a
- * guest.
- */
-
-#include <xen/config.h>
-#include <xen/init.h>
-#include <xen/lib.h>
-#include <xen/types.h>
-#include <xen/sched.h>
-#include <xen/pci.h>
-#include <xen/irq.h>
-#include <xen/event.h>
-#include <asm/pci.h>
-#include <public/xen.h>
-#include <public/physdev.h>
-
-/* Called by PHYSDEV_PCI_INITIALISE_DEVICE to finalise IRQ routing. */
-extern void pcibios_enable_irq(struct pci_dev *dev);
-
-#if 0
-#define VERBOSE_INFO(_f, _a...) printk( _f , ## _a )
-#else
-#define VERBOSE_INFO(_f, _a...) ((void)0)
-#endif
-
-#ifdef VERBOSE
-#define INFO(_f, _a...) printk( _f, ## _a )
-#else
-#define INFO(_f, _a...) ((void)0)
-#endif
-
-#define SLOPPY_CHECKING
-
-#define ACC_READ 1
-#define ACC_WRITE 2
-
-/* Upper bounds for PCI-device addressing. */
-#define PCI_BUSMAX 255
-#define PCI_DEVMAX 31
-#define PCI_FUNCMAX 7
-#define PCI_REGMAX 255
-
-/* Bit offsets into state. */
-#define ST_BASE_ADDRESS 0 /* bits 0-5: are for base address access */
-#define ST_ROM_ADDRESS 6 /* bit 6: is for rom address access */
-
-typedef struct _phys_dev_st {
- int flags; /* flags for access etc */
- struct pci_dev *dev; /* the device */
- struct list_head node; /* link to the list */
- struct domain *owner; /* 'owner of this device' */
- int state; /* state for various checks */
-} phys_dev_t;
-
-
-/* Find a device on a per-domain device list. */
-static phys_dev_t *find_pdev(struct domain *d, struct pci_dev *dev)
-{
- phys_dev_t *t;
- list_for_each_entry ( t, &d->pcidev_list, node )
- if ( dev == t->dev )
- return t;
- return NULL;
-}
-
-static int setup_ioport_memory_access(struct domain *d, struct pci_dev *pdev)
-{
- struct resource *r;
- int i, j;
-
- if ( d->arch.iobmp_mask == NULL )
- {
- if ( (d->arch.iobmp_mask = xmalloc_array(u8, IOBMP_BYTES)) == NULL )
- return -ENOMEM;
- memset(d->arch.iobmp_mask, 0xFF, IOBMP_BYTES);
- }
-
- for ( i = 0; i < DEVICE_COUNT_RESOURCE; i++ )
- {
- r = &pdev->resource[i];
- if ( r->flags & IORESOURCE_IO )
- {
- INFO("Giving domain %u IO resources (%lx - %lx) "
- "for device %s\n", d->id, r->start, r->end, pdev->slot_name);
- for ( j = r->start; j < r->end + 1; j++ )
- clear_bit(j, d->arch.iobmp_mask);
- }
- }
-
- return 0;
-}
-
-void physdev_modify_ioport_access_range(
- struct domain *d, int enable, int port, int num)
-{
- int i;
- for ( i = port; i < (port + num); i++ )
- (enable ? clear_bit : set_bit)(i, d->arch.iobmp_mask);
-}
-
-/* Add a device to a per-domain device-access list. */
-static int add_dev_to_task(struct domain *d, struct pci_dev *dev, int acc)
-{
- phys_dev_t *physdev;
- int rc;
-
- if ( (physdev = xmalloc(phys_dev_t)) == NULL )
- {
- INFO("Error allocating pdev structure.\n");
- return -ENOMEM;
- }
-
- if ( (rc = setup_ioport_memory_access(d, dev)) < 0 )
- {
- xfree(physdev);
- return rc;
- }
-
- physdev->dev = dev;
- physdev->flags = acc;
- physdev->state = 0;
- list_add(&physdev->node, &d->pcidev_list);
-
- if ( acc == ACC_WRITE )
- physdev->owner = d;
-
- return 0;
-}
-
-void physdev_destroy_state(struct domain *d)
-{
- struct list_head *ent;
-
- xfree(d->arch.iobmp_mask);
- d->arch.iobmp_mask = NULL;
-
- while ( (ent = d->pcidev_list.next) != &d->pcidev_list )
- {
- list_del(ent);
- xfree(list_entry(ent, phys_dev_t, node));
- }
-}
-
-/*
- * physdev_pci_access_modify:
- * Allow/disallow access to a specific PCI device. Guests should not be
- * allowed to see bridge devices as it needlessly complicates things (one
- * possible exception to this is the AGP bridge).
- */
-int physdev_pci_access_modify(domid_t dom, int bus, int dev, int func,
- int enable)
-{
- struct domain *p;
- struct pci_dev *pdev;
- phys_dev_t *physdev;
- int rc = 0;
- int oldacc = -1;
-
- BUG_ON(!IS_PRIV(current->domain));
-
- if ( (bus > PCI_BUSMAX) || (dev > PCI_DEVMAX) || (func > PCI_FUNCMAX) )
- return -EINVAL;
-
- if ( !enable )
- {
- INFO("Disallowing access is not yet supported.\n");
- return -EINVAL;
- }
-
- INFO("physdev_pci_access_modify: %02x:%02x:%02x\n", bus, dev, func);
-
- if ( (p = find_domain_by_id(dom)) == NULL )
- return -ESRCH;
-
- /* Make the domain privileged. */
- set_bit(DF_PHYSDEV, &p->d_flags);
- /* FIXME: MAW for now make the domain REALLY privileged so that it
- * can run a backend driver (hw access should work OK otherwise) */
- set_bit(DF_PRIVILEGED, &p->d_flags);
-
- /* Grant write access to the specified device. */
- if ( (pdev = pci_find_slot(bus, PCI_DEVFN(dev, func))) == NULL )
- {
- INFO(" dev does not exist\n");
- rc = -ENODEV;
- goto out;
- }
-
- INFO(" add RW %02x:%02x:%02x\n", pdev->bus->number,
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
-
- if ( (physdev = find_pdev(p, pdev)) != NULL )
- {
- oldacc = physdev->flags;
- physdev->flags = ACC_WRITE;
- }
- else
- {
- rc = add_dev_to_task(p, pdev, ACC_WRITE);
- }
-
- out:
- put_domain(p);
- return rc;
-}
-
-/* Check if a domain controls a device with IO memory within frame @pfn.
- * Returns: 1 if the domain should be allowed to map @pfn, 0 otherwise. */
-int domain_iomem_in_pfn(struct domain *p, unsigned long pfn)
-{
- int ret = 0;
- phys_dev_t *phys_dev;
-
- VERBOSE_INFO("Checking if physdev-capable domain %u needs access to "
- "pfn %p\n", p->id, pfn);
-
- spin_lock(&p->pcidev_lock);
-
- list_for_each_entry ( phys_dev, &p->pcidev_list, node )
- {
- int i;
- struct pci_dev *pci_dev = phys_dev->dev;
-
- for ( i = 0; (i < DEVICE_COUNT_RESOURCE) && (ret == 0); i++ )
- {
- struct resource *r = &pci_dev->resource[i];
-
- if ( r->flags & IORESOURCE_MEM )
- if ( (r->start >> PAGE_SHIFT) == pfn
- || (r->end >> PAGE_SHIFT) == pfn
- || ((r->start >> PAGE_SHIFT < pfn)
- && (r->end >> PAGE_SHIFT > pfn)) )
- ret = 1;
- }
-
- if ( ret != 0 ) break;
- }
-
- spin_unlock(&p->pcidev_lock);
-
- VERBOSE_INFO("Domain %u %s mapping of pfn %p\n",
- p->id, ret ? "allowed" : "disallowed", pfn);
-
- return ret;
-}
-
-/* check if a domain has general access to a device */
-static inline int check_dev_acc(
- struct domain *d, int bus, int dev, int func, phys_dev_t **pdev)
-{
- struct pci_dev *target_dev;
- phys_dev_t *target_pdev;
- unsigned int target_devfn;
-
- *pdev = NULL;
-
- if ( !IS_CAPABLE_PHYSDEV(d) )
- return -EPERM;
-
- if ( (bus > PCI_BUSMAX) || (dev > PCI_DEVMAX) || (func > PCI_FUNCMAX) )
- return -EINVAL;
-
- VERBOSE_INFO("b=%x d=%x f=%x ", bus, dev, func);
-
- /* check target device */
- target_devfn = PCI_DEVFN(dev, func);
- target_dev = pci_find_slot(bus, target_devfn);
- if ( !target_dev )
- {
- VERBOSE_INFO("target does not exist\n");
- return -ENODEV;
- }
-
- /* check access */
- target_pdev = find_pdev(d, target_dev);
- if ( !target_pdev )
- {
- VERBOSE_INFO("dom has no access to target\n");
- return -EPERM;
- }
-
- *pdev = target_pdev;
- return 0;
-}
-
-#ifndef SLOPPY_CHECKING
-/*
- * Base address registers contain the base address for IO regions.
- * The length can be determined by writing all 1s to the register and
- * reading the value again. The device will zero the lower unused bits.
- *
- * to work out the length of the io region a device probe typically does:
- * 1) a = read_base_addr_reg()
- * 2) write_base_addr_reg(0xffffffff)
- * 3) b = read_base_addr_reg() [device zeros lower bits]
- * 4) write_base_addr_reg(a) [restore original value]
- * this function fakes out step 2-4. *no* writes are made to the device.
- *
- * phys_dev_t contains a bit field (a bit for each base address register).
- * if the bit for a register is set the guest had writen all 1s to the
- * register and subsequent read request need to fake out the b.
- * if the guest restores the original value (step 4 above) the bit is
- * cleared again. If the guest attempts to "restores" a wrong value an
- * error is flagged.
- */
-static int do_base_address_access(phys_dev_t *pdev, int acc, int idx,
- int len, u32 *val)
-{
- int st_bit, reg = PCI_BASE_ADDRESS_0 + (idx*4), ret = -EINVAL;
- struct pci_dev *dev = pdev->dev;
- u32 orig_val, sz;
- struct resource *res;
-
- if ( len != sizeof(u32) )
- {
- /* This isn't illegal, but there doesn't seem to be a very good reason
- * to do it for normal devices (bridges are another matter). Since it
- * would complicate the code below, we don't support this for now. */
-
- /* We could set *val to some value but the guest may well be in trouble
- * anyway if this write fails. Hopefully the printk will give us a
- * clue what went wrong. */
- INFO("Guest %u attempting sub-dword %s to BASE_ADDRESS %d\n",
- pdev->owner->id, (acc == ACC_READ) ? "read" : "write", idx);
-
- return -EPERM;
- }
-
- st_bit = idx + ST_BASE_ADDRESS;
- res = &(pdev->dev->resource[idx]);
-
- if ( acc == ACC_WRITE )
- {
- if ( (*val == 0xffffffff) ||
- ((res->flags & IORESOURCE_IO) && (*val == 0xffff)) )
- {
- /* Set bit and return. */
- set_bit(st_bit, &pdev->state);
- ret = 0;
- }
- else
- {
- /* Assume guest wants to set the base address. */
- clear_bit(st_bit, &pdev->state);
-
- /* check if guest tries to restore orig value */
- ret = pci_read_config_dword(dev, reg, &orig_val);
- if ( (ret == 0) && (*val != orig_val) )
- {
- INFO("Guest attempting update to BASE_ADDRESS %d\n", idx);
- ret = -EPERM;
- }
- }
- VERBOSE_INFO("fixed pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x"
- " val=0x%08x %x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- PCI_FUNC(dev->devfn), reg, len, *val, pdev->state);
- }
- else if ( acc == ACC_READ )
- {
- ret = pci_read_config_dword(dev, reg, val);
- if ( (ret == 0) && test_bit(st_bit, &pdev->state) )
- {
- /* Cook the value. */
- sz = res->end - res->start;
- if ( res->flags & IORESOURCE_MEM )
- {
- /* this is written out explicitly for clarity */
- *val = 0xffffffff;
- /* bit 0 = 0 */
- /* bit 21 = memory type */
- /* bit 3 = prefetchable */
- /* bit 4-31 width */
- sz = sz >> 4; /* size in blocks of 16 byte */
- sz = ~sz; /* invert */
- *val = *val & (sz << 4); /* and in the size */
- /* use read values for low 4 bits */
- *val = *val | (orig_val & 0xf);
- }
- else if ( res->flags & IORESOURCE_IO )
- {
- *val = 0x0000ffff;
- /* bit 10 = 01 */
- /* bit 2-31 width */
- sz = sz >> 2; /* size in dwords */
- sz = ~sz & 0x0000ffff;
- *val = *val & (sz << 2);
- *val = *val | 0x1;
- }
- }
- VERBOSE_INFO("fixed pci read: %02x:%02x:%02x reg=0x%02x len=0x%02x"
- " val=0x%08x %x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- PCI_FUNC(dev->devfn), reg, len, *val, pdev->state);
- }
-
- return ret;
-}
-
-
-static int do_rom_address_access(phys_dev_t *pdev, int acc, int len, u32 *val)
-{
- int st_bit, ret = -EINVAL;
- struct pci_dev *dev = pdev->dev;
- u32 orig_val, sz;
- struct resource *res;
-
- if ( len != sizeof(u32) )
- {
- INFO("Guest attempting sub-dword %s to ROM_ADDRESS\n",
- (acc == ACC_READ) ? "read" : "write");
- return -EPERM;
- }
-
- st_bit = ST_ROM_ADDRESS;
- res = &(pdev->dev->resource[PCI_ROM_RESOURCE]);
-
- if ( acc == ACC_WRITE )
- {
- if ( (*val == 0xffffffff) || (*val == 0xfffffffe) )
- {
- /* NB. 0xffffffff would be unusual, but we trap it anyway. */
- set_bit(st_bit, &pdev->state);
- ret = 0;
- }
- else
- {
- /* Assume guest wants simply to set the base address. */
- clear_bit(st_bit, &pdev->state);
-
- /* Check if guest tries to restore the original value. */
- ret = pci_read_config_dword(dev, PCI_ROM_ADDRESS, &orig_val);
- if ( (ret == 0) && (*val != orig_val) )
- {
- if ( (*val != 0x00000000) )
- {
- INFO("caution: guest tried to change rom address.\n");
- ret = -EPERM;
- }
- else
- {
- INFO("guest disabled rom access for %02x:%02x:%02x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- PCI_FUNC(dev->devfn));
- }
- }
- }
- VERBOSE_INFO("fixed pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x"
- " val=0x%08x %x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- PCI_FUNC(dev->devfn), PCI_ROM_ADDRESS, len, *val, pdev->state);
- }
- else if ( acc == ACC_READ )
- {
- ret = pci_read_config_dword(dev, PCI_ROM_ADDRESS, val);
- if ( (ret == 0) && test_bit(st_bit, &pdev->state) )
- {
- /* Cook the value. */
- sz = res->end - res->start;
- *val = 0xffffffff;
- /* leave bit 0 untouched */
- /* bit 1-10 reserved, harwired to 0 */
- sz = sz >> 11; /* size is in 2KB blocks */
- sz = ~sz;
- *val = *val & (sz << 11);
- *val = *val | (orig_val & 0x1);
- }
- VERBOSE_INFO("fixed pci read: %02x:%02x:%02x reg=0x%02x len=0x%02x"
- " val=0x%08x %x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- PCI_FUNC(dev->devfn), PCI_ROM_ADDRESS, len, *val, pdev->state);
- }
-
- return ret;
-
-}
-#endif /* SLOPPY_CHECKING */
-
-#ifdef CONFIG_PCI
-/*
- * Handle a PCI config space read access if the domain has access privileges.
- */
-static long pci_cfgreg_read(int bus, int dev, int func, int reg,
- int len, u32 *val)
-{
- int ret;
- phys_dev_t *pdev;
-
- if ( (ret = check_dev_acc(current->domain, bus, dev, func, &pdev)) != 0 )
- {
- /* PCI spec states that reads from non-existent devices should return
- * all 1s. In this case the domain has no read access, which should
- * also look like the device is non-existent. */
- *val = 0xFFFFFFFF;
- return ret;
- }
-
- /* Fake out read requests for some registers. */
- switch ( reg )
- {
-#ifndef SLOPPY_CHECKING
- case PCI_BASE_ADDRESS_0:
- ret = do_base_address_access(pdev, ACC_READ, 0, len, val);
- break;
-
- case PCI_BASE_ADDRESS_1:
- ret = do_base_address_access(pdev, ACC_READ, 1, len, val);
- break;
-
- case PCI_BASE_ADDRESS_2:
- ret = do_base_address_access(pdev, ACC_READ, 2, len, val);
- break;
-
- case PCI_BASE_ADDRESS_3:
- ret = do_base_address_access(pdev, ACC_READ, 3, len, val);
- break;
-
- case PCI_BASE_ADDRESS_4:
- ret = do_base_address_access(pdev, ACC_READ, 4, len, val);
- break;
-
- case PCI_BASE_ADDRESS_5:
- ret = do_base_address_access(pdev, ACC_READ, 5, len, val);
- break;
-
- case PCI_ROM_ADDRESS:
- ret = do_rom_address_access(pdev, ACC_READ, len, val);
- break;
-#endif
-
- case PCI_INTERRUPT_LINE:
- *val = pdev->dev->irq;
- ret = 0;
- break;
-
- default:
- ret = pci_config_read(0, bus, dev, func, reg, len, val);
- VERBOSE_INFO("pci read : %02x:%02x:%02x reg=0x%02x len=0x%02x "
- "val=0x%08x\n", bus, dev, func, reg, len, *val);
- break;
- }
-
- return ret;
-}
-
-
-/*
- * Handle a PCI config space write access if the domain has access privileges.
- */
-static long pci_cfgreg_write(int bus, int dev, int func, int reg,
- int len, u32 val)
-{
- int ret;
- phys_dev_t *pdev;
-
- if ( (ret = check_dev_acc(current->domain, bus, dev, func, &pdev)) != 0 )
- return ret;
-
- /* special treatment for some registers */
- switch (reg)
- {
-#ifndef SLOPPY_CHECKING
- case PCI_BASE_ADDRESS_0:
- ret = do_base_address_access(pdev, ACC_WRITE, 0, len, &val);
- break;
-
- case PCI_BASE_ADDRESS_1:
- ret = do_base_address_access(pdev, ACC_WRITE, 1, len, &val);
- break;
-
- case PCI_BASE_ADDRESS_2:
- ret = do_base_address_access(pdev, ACC_WRITE, 2, len, &val);
- break;
-
- case PCI_BASE_ADDRESS_3:
- ret = do_base_address_access(pdev, ACC_WRITE, 3, len, &val);
- break;
-
- case PCI_BASE_ADDRESS_4:
- ret = do_base_address_access(pdev, ACC_WRITE, 4, len, &val);
- break;
-
- case PCI_BASE_ADDRESS_5:
- ret = do_base_address_access(pdev, ACC_WRITE, 5, len, &val);
- break;
-
- case PCI_ROM_ADDRESS:
- ret = do_rom_address_access(pdev, ACC_WRITE, len, &val);
- break;
-#endif
-
- default:
- if ( pdev->flags != ACC_WRITE )
- {
- INFO("pci write not allowed %02x:%02x:%02x: "
- "reg=0x%02x len=0x%02x val=0x%08x\n",
- bus, dev, func, reg, len, val);
- ret = -EPERM;
- }
- else
- {
- ret = pci_config_write(0, bus, dev, func, reg, len, val);
- VERBOSE_INFO("pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x "
- "val=0x%08x\n", bus, dev, func, reg, len, val);
- }
- break;
- }
-
- return ret;
-}
-
-
-static long pci_probe_root_buses(u32 *busmask)
-{
- phys_dev_t *pdev;
-
- memset(busmask, 0, 256/8);
-
- list_for_each_entry ( pdev, ¤t->domain->pcidev_list, node )
- set_bit(pdev->dev->bus->number, busmask);
-
- return 0;
-}
-#endif
-
-/*
- * Demuxing hypercall.
- */
-long do_physdev_op(physdev_op_t *uop)
-{
- physdev_op_t op;
- long ret;
- u32 apic, irq;
- u32 address, val;
-
- if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
- return -EFAULT;
-
- switch ( op.cmd )
- {
-#ifdef CONFIG_PCI
- case PHYSDEVOP_PCI_CFGREG_READ:
- ret = pci_cfgreg_read(op.u.pci_cfgreg_read.bus,
- op.u.pci_cfgreg_read.dev,
- op.u.pci_cfgreg_read.func,
- op.u.pci_cfgreg_read.reg,
- op.u.pci_cfgreg_read.len,
- &op.u.pci_cfgreg_read.value);
- break;
-
- case PHYSDEVOP_PCI_CFGREG_WRITE:
- ret = pci_cfgreg_write(op.u.pci_cfgreg_write.bus,
- op.u.pci_cfgreg_write.dev,
- op.u.pci_cfgreg_write.func,
- op.u.pci_cfgreg_write.reg,
- op.u.pci_cfgreg_write.len,
- op.u.pci_cfgreg_write.value);
- break;
-
- case PHYSDEVOP_PCI_INITIALISE_DEVICE:
- if ( (ret = check_dev_acc(current->domain,
- op.u.pci_initialise_device.bus,
- op.u.pci_initialise_device.dev,
- op.u.pci_initialise_device.func,
- &pdev)) == 0 )
- pcibios_enable_irq(pdev->dev);
- break;
-
- case PHYSDEVOP_PCI_PROBE_ROOT_BUSES:
- ret = pci_probe_root_buses(op.u.pci_probe_root_buses.busmask);
- break;
-#endif
- case PHYSDEVOP_IRQ_UNMASK_NOTIFY:
- ret = pirq_guest_unmask(current->domain);
- break;
-
- case PHYSDEVOP_IRQ_STATUS_QUERY:
- irq = op.u.irq_status_query.irq;
- ret = -EINVAL;
- if ( (irq < 0) || (irq >= NR_IRQS) )
- break;
- op.u.irq_status_query.flags = 0;
- /* Edge-triggered interrupts don't need an explicit unmask downcall. */
- if ( strstr(irq_desc[irq].handler->typename, "edge") == NULL )
- op.u.irq_status_query.flags |= PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY;
- ret = 0;
- break;
-#ifdef __ARCH_HAS_IOAPIC
- case PHYSDEVOP_APIC_READ:
- if ( !IS_PRIV(current->domain) )
- return -EPERM;
-
- apic = op.u.apic_op.apic;
- address = op.u.apic_op.offset;
- ret = -EINVAL;
- if (apic >= nr_ioapics)
- break;
- val = io_apic_read(apic, address);
- DPRINTK("ioapic read: %x = %x\n", address, val);
- op.u.apic_op.value = val;
- ret = 0;
- break;
- case PHYSDEVOP_APIC_WRITE:
- if ( !IS_PRIV(current->domain) )
- return -EPERM;
-
- apic = op.u.apic_op.apic;
- address = op.u.apic_op.offset;
- val = op.u.apic_op.value;
- ret = -EINVAL;
- if (apic >= nr_ioapics)
- break;
-
- DPRINTK("ioapic write: %x = %x\n", address, val);
- io_apic_write(apic, address, val);
- ret = 0;
- break;
- case PHYSDEVOP_ASSIGN_VECTOR:
- if ( !IS_PRIV(current->domain) )
- return -EPERM;
-
- irq = op.u.irq_op.irq;
- op.u.irq_op.vector = assign_irq_vector(irq);
- ret = 0;
- break;
-#endif
- case PHYSDEVOP_SET_IOPL:
- ret = -EINVAL;
- if ( op.u.set_iopl.iopl > 3 )
- break;
- ret = 0;
- current->arch.iopl = op.u.set_iopl.iopl;
- break;
-
- case PHYSDEVOP_SET_IOBITMAP:
- ret = -EINVAL;
- if ( !access_ok(op.u.set_iobitmap.bitmap, IOBMP_BYTES) ||
- (op.u.set_iobitmap.nr_ports > 65536) )
- break;
- ret = 0;
- current->arch.iobmp = (u8 *)op.u.set_iobitmap.bitmap;
- current->arch.iobmp_limit = op.u.set_iobitmap.nr_ports;
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- if (copy_to_user(uop, &op, sizeof(op)))
- ret = -EFAULT;
-
- return ret;
-}
-
-/* opt_physdev_dom0_hide: list of PCI slots to hide from domain 0. */
-/* Format is '(%02x:%02x.%1x)(%02x:%02x.%1x)' and so on. */
-static char opt_physdev_dom0_hide[200] = "";
-string_param("physdev_dom0_hide", opt_physdev_dom0_hide);
-
-/* Test if boot params specify this device should NOT be visible to DOM0
- * (e.g. so that another domain can control it instead) */
-static int pcidev_dom0_hidden(struct pci_dev *dev)
-{
- char cmp[10] = "(.......)";
-
- strncpy(&cmp[1], dev->slot_name, 7);
-
- if ( strstr(opt_physdev_dom0_hide, dev->slot_name) == NULL )
- return 0;
-
- return 1;
-}
-
-
-/* Domain 0 has read access to all devices. */
-void physdev_init_dom0(struct domain *d)
-{
- struct pci_dev *dev;
- phys_dev_t *pdev;
-
- /* Access to all I/O ports. */
- d->arch.iobmp_mask = xmalloc_array(u8, IOBMP_BYTES);
- BUG_ON(d->arch.iobmp_mask == NULL);
- memset(d->arch.iobmp_mask, 0, IOBMP_BYTES);
-
- /* Access to all PCI devices. */
- pci_for_each_dev(dev)
- {
- if ( pcidev_dom0_hidden(dev) )
- {
- printk("Hiding PCI device %s from DOM0\n", dev->slot_name);
- continue;
- }
-
- pdev = xmalloc(phys_dev_t);
- BUG_ON(pdev == NULL);
-
- pdev->dev = dev;
- pdev->flags = ACC_WRITE;
- pdev->state = 0;
- pdev->owner = d;
- list_add(&pdev->node, &d->pcidev_list);
- }
-
- set_bit(DF_PHYSDEV, &d->d_flags);
-}
-
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
#include <xen/reboot.h>
#include <xen/sched.h>
#include <xen/serial.h>
-#include <xen/physdev.h>
#include <asm/io.h>
+#ifdef CONFIG_X86
+#include <asm/physdev.h>
+#endif
+
/* Config serial port with a string <baud>,DPS,<io-base>,<irq>. */
static char opt_com1[30] = OPT_COM1_STR, opt_com2[30] = OPT_COM2_STR;
string_param("com1", opt_com1);
void serial_endboot(void)
{
+#ifdef CONFIG_X86
int i;
for ( i = 0; i < ARRAY_SIZE(com); i++ )
if ( UART_ENABLED(&com[i]) )
physdev_modify_ioport_access_range(dom0, 0, com[i].io_base, 8);
+#endif
}
/*
#define ELFSIZE 32
#endif
-#define __ARCH_HAS_IOAPIC
-
#endif /* __X86_CONFIG_H__ */
--- /dev/null
+/******************************************************************************
+ * physdev.h
+ */
+
+#ifndef __XEN_PHYSDEV_H__
+#define __XEN_PHYSDEV_H__
+
+#include <public/physdev.h>
+
+void physdev_modify_ioport_access_range(
+ struct domain *d, int enable, int port, int num );
+void physdev_destroy_state(struct domain *d);
+int domain_iomem_in_pfn(struct domain *p, unsigned long pfn);
+long do_physdev_op(physdev_op_t *uop);
+void physdev_init_dom0(struct domain *d);
+
+#endif /* __XEN_PHYSDEV_H__ */
memory_t free_pages;
} dom0_physinfo_t;
-/*
- * Allow a domain access to a physical PCI device
- */
-#define DOM0_PCIDEV_ACCESS 23
-typedef struct {
- /* IN variables. */
- domid_t domain;
- u32 bus;
- u32 dev;
- u32 func;
- u32 enable;
-} dom0_pcidev_access_t;
-
/*
* Get the ID of the current scheduler.
*/
dom0_pincpudomain_t pincpudomain;
dom0_tbufcontrol_t tbufcontrol;
dom0_physinfo_t physinfo;
- dom0_pcidev_access_t pcidev_access;
dom0_sched_id_t sched_id;
dom0_shadow_control_t shadow_control;
dom0_setdomainmaxmem_t setdomainmaxmem;
-/****************************************************************************
- * (c) 2004 - Rolf Neugebauer - Intel Research Cambridge
- * (c) 2004 - Keir Fraser - University of Cambridge
- ****************************************************************************
- * Description: Interface for domains to access physical devices on the PCI bus
- */
#ifndef __XEN_PUBLIC_PHYSDEV_H__
#define __XEN_PUBLIC_PHYSDEV_H__
/* Commands to HYPERVISOR_physdev_op() */
-#define PHYSDEVOP_PCI_CFGREG_READ 0
-#define PHYSDEVOP_PCI_CFGREG_WRITE 1
-#define PHYSDEVOP_PCI_INITIALISE_DEVICE 2
-#define PHYSDEVOP_PCI_PROBE_ROOT_BUSES 3
#define PHYSDEVOP_IRQ_UNMASK_NOTIFY 4
#define PHYSDEVOP_IRQ_STATUS_QUERY 5
#define PHYSDEVOP_SET_IOPL 6
#define PHYSDEVOP_APIC_WRITE 9
#define PHYSDEVOP_ASSIGN_VECTOR 10
-/* Read from PCI configuration space. */
-typedef struct {
- /* IN */
- u32 bus; /* 0 */
- u32 dev; /* 4 */
- u32 func; /* 8 */
- u32 reg; /* 12 */
- u32 len; /* 16 */
- /* OUT */
- u32 value; /* 20 */
-} PACKED physdevop_pci_cfgreg_read_t; /* 24 bytes */
-
-/* Write to PCI configuration space. */
-typedef struct {
- /* IN */
- u32 bus; /* 0 */
- u32 dev; /* 4 */
- u32 func; /* 8 */
- u32 reg; /* 12 */
- u32 len; /* 16 */
- u32 value; /* 20 */
-} PACKED physdevop_pci_cfgreg_write_t; /* 24 bytes */
-
-/* Do final initialisation of a PCI device (e.g., last-moment IRQ routing). */
-typedef struct {
- /* IN */
- u32 bus; /* 0 */
- u32 dev; /* 4 */
- u32 func; /* 8 */
-} PACKED physdevop_pci_initialise_device_t; /* 12 bytes */
-
-/* Find the root buses for subsequent scanning. */
-typedef struct {
- /* OUT */
- u32 busmask[256/32]; /* 0 */
-} PACKED physdevop_pci_probe_root_buses_t; /* 32 bytes */
-
typedef struct {
/* IN */
u32 irq; /* 0 */
u32 apic; /* 0 */
u32 offset;
/* IN or OUT */
- u64 value;
+ u32 value;
} PACKED physdevop_apic_t;
typedef struct {
u32 cmd; /* 0 */
u32 __pad; /* 4 */
union { /* 8 */
-#ifdef CONFIG_PCI
- physdevop_pci_cfgreg_read_t pci_cfgreg_read;
- physdevop_pci_cfgreg_write_t pci_cfgreg_write;
- physdevop_pci_initialise_device_t pci_initialise_device;
- physdevop_pci_probe_root_buses_t pci_probe_root_buses;
-#endif
physdevop_irq_status_query_t irq_status_query;
physdevop_set_iopl_t set_iopl;
physdevop_set_iobitmap_t set_iobitmap;
+++ /dev/null
-/******************************************************************************
- * physdev.h
- */
-
-#ifndef __XEN_PHYSDEV_H__
-#define __XEN_PHYSDEV_H__
-
-#include <public/physdev.h>
-
-void physdev_modify_ioport_access_range(
- struct domain *d, int enable, int port, int num );
-void physdev_destroy_state(struct domain *d);
-int physdev_pci_access_modify(
- domid_t dom, int bus, int dev, int func, int enable);
-int domain_iomem_in_pfn(struct domain *p, unsigned long pfn);
-long do_physdev_op(physdev_op_t *uop);
-void physdev_init_dom0(struct domain *d);
-
-#endif /* __XEN_PHYSDEV_H__ */
u16 pirq_to_evtchn[NR_PIRQS];
u32 pirq_mask[NR_PIRQS/32];
- /* Physical I/O */
- spinlock_t pcidev_lock;
- struct list_head pcidev_list;
-
unsigned long d_flags;
unsigned long vm_assist;